package org.traffometer.traffobase.webapp.control;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.traffometer.traffobase.model.DerbyPacketStore;
import org.traffometer.traffobase.model.PacketStore;
import org.traffometer.traffobase.webapp.control.command.Command;

//import org.traffometer.traffobase.webapp.control.Page;

/**
 * The central servlet that serves as the controller in the MVC pattern
 * for JSP page dispatching.
 *
 * @author Philip M. Johnson
 * @author Jitender Miglani (did minor changes)
 */
@SuppressWarnings("serial")
public class Controller extends HttpServlet {

  private String exceptionAttribute = "javax.servlet.jsp.jspException";
  private String commandParameter = "CommandName";
  private static String dbURL = "jdbc:derby://localhost:1527/traffoPacketdb;create=true";
  
  /**
   * The key to be used to retrieve the persistent stack instance from the Servlet context.
   */
  public static final String STACK_KEY = "org.traffometer.traffobase.PacketStore";
  
  /**
   * The key to be used to retrieve the connection to the database.
   */
  public static final String DBCONNECTION_KEY = "org.traffometer.traffobase.connection";

  /**
   * Initializes the Traffobase system by setting up a PacketStore as an
   * attribute in the servlet context.
   *
   * @exception ServletException If errors occur during initialization.
   */
  public void init() throws ServletException {
    getServletContext().log("Initializing Traffobase.");
    getServletContext().setAttribute(Controller.STACK_KEY, getPersistentStore());
  }
  
  /**
   * Returns the connection to the Derby network database. Called in the case of Derby persistency
   * mechanism.
   * 
   * @return the connection to the database.
   */
  public static Connection getConnection() {
      Connection conn = null;
      try {
          Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
          //Get a connection
          conn = DriverManager.getConnection(dbURL); 
      }
      catch (Exception e) {
          e.printStackTrace();
      }
      return conn;
  }
  
  
  /**
   * Inspects the ServletContext init-param to determine what flavor of stack to instantiate. If the
   * init-param for PersistencyMechanism in the web.xml file is set to JDOM, then use JDOM-based
   * persistence. If set to Properties, use Properties, otherwise use Serializable.
   * 
   * @return The PersistentStack instance to be used.
   */
  private PacketStore getPersistentStore() {
    String dbLocation = getServletConfig().getInitParameter("DBLocation");
    String persistencyMechanism = getServletConfig().getInitParameter("PersistencyMechanism");

    PacketStore store = null;
    if ("Derby".equals(persistencyMechanism)) {
      System.out.println("Using Derby persistence");
      //Connection dbConnection = getConnection(dbLocation);
      Connection dbConnection = getConnection();
      getServletContext().setAttribute(Controller.DBCONNECTION_KEY, dbConnection);
      //store = new DerbyPacketStore(getServletContext());
      store = new DerbyPacketStore(Controller.DBCONNECTION_KEY, dbConnection);
    }
    return store;
  }

  /**
   * Receives all user requests and dispatches to appropriate command class
   * for processing. The command class is determined by the value of the "CommandName"
   * parameter in the request; if none is supplied, then "Clear" is assumed.
   * The command class that is dispatched from this method returns the page that should be
   * displayed in response to the user request.  The command class that is dispatched from
   * this method is responsible for updating the request object with new attributes required by
   * the JSP page.
   *
   * @param request The servlet request object.
   * @param response The servlet response object.
   * @exception ServletException If problems occur with the request or rsponse.
   * @exception IOException If problems occur during request forwarding.
   */
  public void doPost(HttpServletRequest request, HttpServletResponse response)
       throws ServletException, IOException {

    //Every request to this servlet must include the "CommandName" parameter.
    String commandName = request.getParameter(commandParameter);
    System.err.println(commandName);
    RequestDispatcher dispatcher;

    // Start out with a cleared ErrorMessage attribute.
    request.setAttribute("errorMessage", "");

    //If no commandName param, assume just "index.jsp" URL and initialize.
    if (commandName == null) {
      commandName = "Clear";
    }

    // Now try to dispatch to the command class responsible for handling the requested Command.
    try {
      String commandClassName = "org.traffometer.traffobase.webapp.control.command." +
        commandName + "Command";
      Command command = (Command) Class.forName(commandClassName).newInstance();
      
      //PacketStore pkStore = (PacketStore) getServletContext().getAttribute(STACK_KEY);
      PacketStore pkStore = (PacketStore) getPersistentStore();
      Page page = command.process(request, pkStore);
      request.setAttribute("PageTitle", page.getTitle());
      dispatcher = getServletContext().getRequestDispatcher(page.getFileName());
    }
    catch (Exception e) {
      request.setAttribute(exceptionAttribute, e);
      dispatcher = getServletContext().getRequestDispatcher(Page.ERROR.getFileName());
    }

    // Now forward the updated request object on to the page that will be returned to the user.
    dispatcher.forward(request, response);
  }


  /**
   * Dispatches to doPost for processing.
   *
   * @param request The servlet request.
   * @param response The servlet response.
   * @exception ServletException If problems during request/response processing.
   * @exception IOException If problems during the forward to the JSP page.
   */
  public void doGet(HttpServletRequest request, HttpServletResponse response)
       throws ServletException, IOException {
    doPost(request, response);
  }
}